/**
 * t.gen 1.0 http://www.technopoli.ipn.mx/
 * 
 * By: Ramón Rivera
 */

(function(window) {
	window.Gen = {
		/* Dictionary */
		Dict : function(array) {
			var mValues = [];

			this.addArray = function(pairs) {
				for (var i = 0; i < pairs.length; i++)
					this.add(pairs[i].key, pairs[i].value);
			}

			this.add = function(key, value) {
				mValues.push({
					key : key,
					value : value
				});
			}

			this.getValue = function(key) {
				var result = null;

				for (var i = 0; i < mValues.length; i++)
					if (mValues[i].key == key)
						return mValues[i].value;

			}

			this.asArray = function() {
				return mValues;
			}

			this.length = function() {
				return mValues.length;
			}

			this.removeValue = function(key) {
				removeValue(mValues, "key", key, 1);
			}

			if (array != undefined && array != null)
				this.addArray(array);
		},
		/* Validate thorugh javascript */
		Validator : function(tagName) {
			this.tagName = tagName;

			this.textExpressions = new Gen.Dict([ {
				key : 'blank-text',
				value : new RegExp("^[a-zA-Z0-9áéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ \-.]{0,}$")
			}, {
				key : 'text',
				value : new RegExp("^[a-zA-Z0-9áéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ \-.]{1,}$")
			}, {
				key : 'text-spaces',
				value : new RegExp("^[a-zA-Z0-9áéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ \-.]{1,}$")
			}, {
				key : 'capital',
				value : new RegExp("^[A-Z]{1,}$")
			}, {
				key : 'blank-text-enter',
				value : new RegExp("^[a-zA-Z0-9áéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ \-.\n]{1,}$")
			}, {
				key : 'capital-acc',
				value : new RegExp("^[A-ZÁÉÍÓÚÀÈÌÒÙ]{1,}$")
			}, {
				key : 'lowers',
				value : new RegExp("^[a-z]{1,}$")
			}, {
				key : 'lowers-acc',
				value : new RegExp("^[a-záéíóúàèìòù]{1,}$")
			}, {
				key : 'letters',
				value : new RegExp("^[a-zA-Z]{1,}$")
			}, {
				key : 'letters-numbers',
				value : new RegExp("^[a-zA-Z0-9]{1,}$")
			}, {
				key : 'mail',
				value : new RegExp(/[\w-\.]{3,}@([\w-]{2,}\.)*([\w-]{2,}\.)[\w-]{2,4}/)
			}, {
				key : 'website',
				value : new RegExp("^(ht|f)tp(s?)\://[0-9a-zA-Z]([-_./]*[0-9a-zA-Z])*(:[0-9]{0,6})*(/?)*([0-9a-zA-Z/._-]{0,})?$")
			}, {
				key : 'phone',
				value : new RegExp("^[0-9-]{10,}(?!/-+/)$")
			}, {
				key : 'number',
				value : new RegExp("^[0-9.,]{1,}$")
			}, {
				key : 'just-numbers',
				value : new RegExp("^[0-9]{1,}$")
			}, {
				key : 'number-space',
				value : new RegExp("^[0-9 ]{1,}$")
			}, {
				key : 'password',
				value : new RegExp("^[a-zA-Z0-9@+#-_]{6,15}$")
			}, {
				key : 'dateYYYYMMDD',
				value : new RegExp("^[0-9]{4}/[0-9]{2}/[0-9]{2}$")
			}, {
				key : 'curp',
				value : new RegExp("^[a-zA-Z]{4}[0-9]{6}[a-zA-Z0-9]{8}$")
			}, {
				key : 'codpost',
				value : new RegExp("^[0-9]{5}$")
			}]);

			this.selectValidations = new Gen.Dict([ {
				key : 'selected',
				value : function(field, self) {
					var $field = $(field);

					var wrong = $field.attr('wrongOption') | -1;
					if ($field.find('option:selected').val() == wrong)
						return false;

					return true;
				}
			} ]);

			this.typeValidation = {
				text : 'text',
				hidden : 'text',
				textarea : 'text',
				'select-one' : 'select',
				password : 'password'
			};

			this.addTextExpression = function(expression) {
				this.textExpressions.push(expression);
			}

			this.addSelectValidateFunction = function(validateFunction) {
				this.selectValidations.push(validateFunction);
			}

			this.validate = function(parent, afterFuction) {
				var fields = parent.find('[' + this.tagName + ']');
				var wrongOnes = [];
				var type;
				for (var i = 0; i < fields.length; i++)
					mUIHelper.TBox.clearError((fields[i]));

				for (var i = 0; i < fields.length; i++) {
					type = fields[i].type;

					// if ($(fields[i]).is(':visible')) {
					if ($(fields[i]).is(':enabled')) {
						switch (this.typeValidation[type]) {
						case "text":
						case "password":
							if (!validateText(fields[i], this)) {
								wrongOnes.push($(fields[i]));
								mUIHelper.TBox.markError($(fields[i]));
							}

							break;
						case "select":
							if (!validateSelect(fields[i], this)) {
								wrongOnes.push($(fields[i]));
								mUIHelper.TBox.markError($(fields[i]));
							}

							break;
						}
					}
				}

				if (afterFuction != null)
					afterFuction(wrongOnes);

				return wrongOnes;
			}

			this.clear = function(parent) {
				var fields = parent.find('[' + this.tagName + ']');

				for (var i = 0; i < fields.length; i++)
					mUIHelper.TBox.clearError((fields[i]));
			}

			function validateText(field, self) {
				var success = true;
				var tags = $(field).attr(self.tagName).split(' ');

				for (var i = 0; i < tags.length; i++)
					if (!self.textExpressions.getValue(tags[i]).test($(field).val())) {
						success = false;
						break;
					}

				return success;
			}

			function validateSelect(field, self) {
				var success = true;
				var tags = $(field).attr(self.tagName).split(' ');
				var validateFunction = function() {
				};

				for (var i = 0; i < tags.length; i++) {
					validateFunction = self.selectValidations.getValue(tags[i]);
					success = !success ? false : validateFunction(field, self);

					if (!success)
						break;
				}

				return success;
			}
		},
		/* Ajax calls, get, post, get with padding */
		AjaxCall : function(options) {
			this.options = extend(Gen.AjaxCall.prototype.init, options);

			this.get = function(url, data, success, error) {
				var opt = extendOptions({
					data : data,
					url : url,
					success : success,
					error : error
				});

				this.options.type = "GET";

				this.g(opt);
			}

			this.post = function(url, data, success, error) {
				var opt = extendOptions({
					data : data,
					url : url,
					success : success,
					error : error
				});

				this.g(opt);
			}

			this.getPadding = function(url, data, success, error, jsonCallback) {
				var op = extendOptions({
					data : data,
					url : url,
					success : success,
					error : error
				});

				this.options.type = "get";
				this.options.dataType = "jsonp";
				this.options.jsonpCallback = jsonCallback;

				this.g(op);
			}

			function extendOptions(o) {
				var r = {
					data : o.data || {},
					url : o.url || null,
					success : o.success || function() {
					},
					error : o.error || function() {
					},
					redirectURL : o.redirectURL || ""
				}

				return r
			}
		},
		UIHelper : function() {
			Gen.UIHelper.prototype.TBox = {
				types : [ "user", "school", "web", "phone", "mail", "password", "enterprise", "date" ],
				createDateField : function(field, onSelectFunc) {
					var $field = $(field);
					if (!$field.is('t-box'))
						$field.addClass('t-box');

					field.datepicker({
						beforeShow : function() {
							setTimeout(function() {
								$('.ui-datepicker').css('z-index', 9999);
							}, 0);
						},
						dateFormat : "yy-mm-dd",
						onSelect : function(date) {
							this.focus();
							onSelectFunc(date);
						},
						monthNames : [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre",
								"Octubre", "Noviembre", "Diciembre" ],
						dayNamesMin : [ "Dom", "Lun", "Mar", "Mier", "Jue", "Vie", "Sa" ]
					});
				},
				create : function(field, callback) {
					var $field = $(field);
					callback = callback || function() {
					};
					if (!$field.is('t-box'))
						$field.addClass('t-box');

					var mTemplate = $("<div class='tbox-cont'></div>");
					var mField = createChild($field, this);
					var mParent = $field.parent();
					var mID = $field.attr('id');

					mTemplate.append(mField);
					$field.remove();
					mParent.append(mTemplate);

					if ($field.attr('t-box-type') == "date") {
						this.createDateField(mParent.find('#' + mID), callback);
					}

					function createChild($field, self) {
						var span = $('<span class="type-tbox ' + $field.attr('t-box-type') + '"></span>');
						var cont = $('<div/>');
						var f = cont.append(span).append($field.clone());

						return f;
					}
				},
				markError : function(field) {
					var $field = $(field);
					$field.parent().children().addClass('t-error');
				},
				clearError : function(field) {
					var $field = $(field);
					$field.parent().children().removeClass('t-error');
				}
			}

			this.Pagination = function(field) {
				this.create = function(options) {
					field.paginate({
						count : options.max || Gen.UIHelper.prototype.init.Pagination.max,
						start : options.max || Gen.UIHelper.prototype.init.Pagination.start,
						display : options.display || Gen.UIHelper.prototype.init.Pagination.display,
						border : true,
						border_color : '#fff',
						text_color : '#fff',
						background_color : '#7a0000',
						border_hover_color : '#ccc',
						text_hover_color : '#000',
						background_hover_color : '#fff',
						images : false,
						mouse : 'press',
						onChange : options.updateFunction || Gen.UIHelper.prototype.init.Pagination.updateFunction
					});
				}
			}

			this.fillCombo = function(data, field, key, value, clear, showNone) {
				var arr = [];
				var $field = $(field);

				clear = clear || false;
				key = key || "ID";
				value = value || "value";

				if (clear)
					$field.find('option').remove().end();

				if (showNone)
					$field.append($("<option></option>").attr("value", -1).text(this.init.Select.noneValue));

				for (var i = 0; i < data.length; i++) {
					$field.append($("<option></option>").attr("value", data[i][key]).text(data[i][value]));
					arr.push({
						key : data[i][key],
						value : data[i][value]
					});
				}

				return arr;
			}

		}
	}

	/* UI */
	var mUIHelper = new Gen.UIHelper();
	var mSpinner = null;

	$(window.document).ready(function() {
		$('.t-box').each(function() {
			mUIHelper.TBox.create(this);
		});
	});

	/* General purpose functions */
	window.replaceAll = function(string, char, replaceChar) {
		while (string.indexOf(char) != -1)
			string = string.replace(char, replaceChar);

		return string;
	}

	window.secsToTime = function(val) {
		var hours = Math.floor(val / 3600);
		var minutes = Math.floor((val % 3600) / 60);
		var seconds = val % 60;

		minutes = minutes < 10 ? '0' + minutes : minutes;

		seconds = seconds < 10 ? '0' + seconds : seconds;

		var result = hours == 0 ? minutes + ":" + seconds : hours + ":" + minutes + ":" + seconds;

		return result;
	}

	window.removeValue = function(data, key, value, numberItems) {
		numberItems = numberItems || 1;

		for (var i = data.length - 1; i >= 0; i--)
			if (data[i][key] == value)
				data.splice(i, numberItems);
	}

	window.findValue = function(data, key, value) {
		for (var i = 0; i < data.length; i++)
			if (data[i][key] == value)
				return data[i];

		return null;
	}

	window.String.prototype.format = function() {
		var a = arguments;
		return this.replace(/{(\d+)}/g, function(m, n) {
			return typeof a[n] != 'undefined' ? a[n] : m;
		});
	};

	window.showOverlay = function(wait) {
		var overlay = $('<div id="t-overlay"> </div>');
		overlay.appendTo(document.body)

		if (wait) {
			var target = document.getElementById('t-overlay');
			mSpinner = new Spinner({
				lines : 12,
				length : 20,
				width : 10,
				radius : 30,
				corners : 1,
				rotate : 0,
				direction : 1,
				color : '#fff',
				speed : 1,
				trail : 60,
				shadow : false,
				hwaccel : false,
				className : 'spinner',
				zIndex : 2e9,
				top : '50%',
				left : '50%'
			}).spin(target);
		}
	}

	window.hideOverlay = function() {
		$('#t-overlay').remove();
		if (mSpinner != null) {
			mSpinner.stop();
			mSpinner = null;
		}
	}

	/* Help inner functions */
	function extend(a, b) {
		var p = {};
		for ( var key in a) {
			if (b != undefined && b.hasOwnProperty(key))
				p[key] = b[key];
			else
				p[key] = a[key];

		}
		return p;
	}

	/* UIHelper prototype */
	Gen.UIHelper.prototype.init = {
		Select : {
			noneValue : ".. Seleccionar .."
		},
		Pagination : {
			max : 10,
			start : 0,
			display : 10,
			updateFunction : function(page) {
			}
		}
	}

	/* Ajax Call protoype */
	Gen.AjaxCall.prototype.init = {
		type : 'POST',
		dataType : 'json',
		jsonpCallback : '',
	};

	Gen.AjaxCall.prototype.options = {};

	Gen.AjaxCall.prototype.g = function(o) {
		$.ajax({
			url : o.url,
			redirectURL : o.redirectURL,
			type : this.options.type,
			data : o.data,
			dataType : this.options.dataType,
			success : o.success,
			jsonpCallback : this.options.jsonpCallback,
			error : function(er) {
				if (er.status == 404)
					o.error(er.status + " - " + er.statusText);
				else if (er.status == 500) {
					var ms = er.responseJSON == null ? "" : er.responseJSON.Message;
					o.error(er.status + " - " + ms);
				}
			}
		});
	}
})(window);
